package middlewares

import (
	"api.fenglide.com.cn/models"
	"crypto/md5"
	"encoding/hex"
	"github.com/astaxie/beego/context"
	"github.com/garyburd/redigo/redis"
	"strconv"
	"strings"
	"time"
)

//过滤器
//前置
var Before = func(ctx *context.Context) {
	/**
	请求头校验
	请求时数据时time表示时间戳 纬度必须介于10秒内 pk公钥 sk私钥
	公共token加密规则
	Token=md5(sha1(sha1(pk)+sk)+time) 校验需要接收用户的sk参数
	若是以用户的身份访问需要携带Sign 服务端会校验 通过后即放行
	*/
	//不在error路由使用校验
	unixTime := time.Now() //后台当前的时间
	oldUnixTime := unixTime.Add(-time.Minute * 5).Unix()
	if !strings.Contains(ctx.Request.RequestURI, "/error/") {
		//校验是否为Post提交
		if ctx.Request.Method != "POST" {
			ctx.Redirect(307, "/error/post")
		}
		values := ctx.Request.Header
		token := values["Sign"]
		sk := values["Sk"]
		cTime := values["Ctime"]
		//时间戳为空跳出
		if cTime==nil{
			ctx.Redirect(307, "/error/err")
		}
		//字符串转为int64格式
		rowCtime, _ := strconv.ParseInt(cTime[0], 10, 64)
		i := rowCtime - oldUnixTime
		//超过300时间戳过期
		if i>300{
			ctx.Redirect(307, "/error/err")
		}
		//token为空 sk为空 跳出
		if token == nil || sk == nil {
			ctx.Redirect(307, "/error/err")
		}
		//校验token是否与参数一致
		rc := models.RedisPool().Get()
		defer rc.Close()
		key, err := redis.String(rc.Do("hGet", "API_PK_SK", sk[0]))
		if err != nil {
			ctx.Redirect(307, "/error/err")
		}
		//因为存入redis的pk和sk是已经sha1加密过的所以直接取出拼接时间戳
		var signS strings.Builder
		signS.WriteString(key)
		signS.WriteString(strconv.Itoa(int(rowCtime))) //整数转为字符串
		//md5加密
		md5 := md5.New()
		md5.Write([]byte(signS.String()))
		sign := hex.EncodeToString(md5.Sum(nil))
		if sign != token[0] {
			ctx.Redirect(307, "/error/err")
		}
		//通过放行
	}
}
